package com.ruoyi.framework.aspectj;

import com.ruoyi.common.exception.BaseException;
import com.ruoyi.common.utils.sign.Base64;
import com.ruoyi.framework.config.RuoYiConfig;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.util.Objects;

@Aspect
@Component
public class SignatureValidation {
    private final Logger logger = LoggerFactory.getLogger(SignatureValidation.class);

    /**
     * 时间戳请求最小限制(30s)
     * 设置的越小，安全系数越高，但是要注意一定的容错性
     */
    private static final long MAX_REQUEST = 30 * 1000L;
    /**
     * 秘钥
     */
    private static final String SECRET= "yuze";

    /**
     * 验签切点(完整的找到设置的文件地址)
     */
    @Pointcut("execution(@com.ruoyi.framework.aspectj.lang.annotation.SignatureValidation * *(..))")
    private void verifyUserKey() {
    }

    /**
     * 开始验签
     */
    @Before("verifyUserKey()")
    public void doBasicProfiling() {
        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        String token = request.getHeader("token");
        String timestamp = request.getHeader("timestamp");
        try {
            Boolean check = checkToken(token, timestamp);
            if (!check) {
                // 自定义异常抛出（开发者自行换成自己的即可）
                throw new BaseException("签名验证错误");
            }
        } catch (Throwable throwable) {
            // 自定义异常抛出（开发者自行换成自己的即可）
            throw new BaseException("签名验证错误,时间戳超时");
        }
    }

    /**
     * 校验token
     *
     * @param token     签名
     * @param timestamp 时间戳
     * @return 校验结果
     */
    private Boolean checkToken(String token, String timestamp) {
        if("dev".equals(RuoYiConfig.getActive())){
            return true;
        }
        if (StringUtils.isAnyBlank(token, timestamp)) {
            return false;
        }
        long now = System.currentTimeMillis();
        long time = Long.parseLong(timestamp);
        if (now - time > MAX_REQUEST) {
            throw new BaseException("时间戳时间已过");
        }
        String crypt="";
        try {
             crypt = Base64.encode((SECRET+ timestamp).getBytes("utf-8"));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return StringUtils.equals(crypt, token);
    }

    public static void main(String[] args) {
        long times=System.currentTimeMillis();
        System.out.println(times);
        try {
            System.out.println(Base64.encode((SECRET+ times).getBytes("UTF-8")));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }

}
